<template>
	<Teleport to="#desktop">
		<div class="window" v-show="!props.setting.min" @mousedown="onFocus(props.setting.id)"
			:class="{ focus: props.setting.focus, animating: data.animating, maximized: data.maximized, bounceIn: data.animatedIn, zoomOut: data.animatedOut }"
			:style="{ top: data.position.y + 'px', left: data.position.x + 'px', width: data.width + 'px', height: data.height + 'px', 'z-index': props.setting.index }">
			<header class="window-title" @mousedown.self="onMousedown($event)" @dblclick.self="onMax()">
				<div class="icon" :class="props.setting.icon"></div>
				{{ props.setting.title }}
				<div class="window-control">
					<span class="button min" @mousedown="onMin(props.setting.id)"
						v-show="props.setting.resizable"></span>
					<span class="button max" @mousedown="onMax()" v-show="props.setting.resizable"></span>
					<span class="button close" @mousedown="onClose(props.setting.id)"></span>
				</div>
			</header>
			<div class="window-body" :ref="'window_' + props.setting.id">
				<keep-alive>
					<component :is="subComponent" v-model:window="window"></component>
				</keep-alive>
			</div>
			<div class="resize-overlay" v-show="data.overlayShow"></div>
			<div class="resize-side" v-for="(value, index) in data.resizeSide" :key="index" v-show="data.resizable"
				:class="value" @mousedown.self="onResize(value)"></div>
		</div>
	</Teleport>
</template>

<script setup>
	import {reactive, defineProps, defineEmits, onBeforeMount, onMounted, computed, defineAsyncComponent, shallowRef} from 'vue';
	import loadingComponent from './loading.vue'
	import errorComponent from './error.vue'
	import coreStore from '../stores/core.js';
	const $coreStore = coreStore();

	const props = defineProps({
		setting: {
			type: Object,
			default: {
				id: String,
				focus: Boolean,
				hidden: Boolean,
				index: Number
			}
		}
	});
	
	const subComponent = shallowRef(null);
	
	const data = reactive({
		//subComponent: {},
		timer: {},
		drag: false,
		resize: false,
		width: 200,
		height: 400,
		maximized: false,
		animating: false,
		animatedIn: false,
		animatedOut: false,
		resizable: true,
		position: {
			x: 0,
			y: 0
		},
		oldposition: {},
		overlayShow: false,
		resizeSide: ['side-top', 'side-bottom', 'side-left', 'side-right', 'angle-top-left', 'angle-top-right',
			'angle-bottom-left', 'angle-bottom-right'
		]
	});

	const window = computed(() => {
		return {
			width: data.width,
			height: data.height,
			id: props.setting.id
		};
	});

	onBeforeMount(() => {
		let w = document.body.clientWidth;
		let h = document.body.clientHeight;
		data.width = props.setting.width > 0 ? props.setting.width : w / 2;
		data.height = props.setting.height > 0 ? props.setting.height : w / 3;
		data.resizable = props.setting.resizable
		data.position.x = w / 2 - data.width / 2;
		data.position.y = (h - data.height) / 2;
		data.animatedIn = true;
		let dirs = props.setting.page.split('/');
		if(dirs.length >= 2){
			subComponent.value = defineAsyncComponent({
				loader: () => import(`../applications/${dirs[0]}/${dirs[1]}.vue`),
				loadingComponent: loadingComponent,
				errorComponent: errorComponent,
				delay: 500
			});
		} else {
			subComponent.value = defineAsyncComponent({
				loader: () => import(`../applications/${dirs[0]}.vue`),
				loadingComponent: loadingComponent,
				errorComponent: errorComponent,
				delay: 500
			});
		}
	});

	onMounted(() => {
		data.animatedIn = true;
		clearTimeout(data.timer);
		data.timer = setTimeout(() => {
			clearTimeout(data.timer);
			data.animatedIn = false;
		}, 400);
	});

	const onFocus = function(id) {
		$coreStore.applicationFocus(id);
	}

	const onClose = function(id) {
		data.animatedOut = true
		clearTimeout(data.timer);
		data.timer = setTimeout(() => {
			clearTimeout(data.timer);
			$coreStore.closeApplication(id);
		}, 300)
	}
	const onMin = function(id) {
		$coreStore.applicationMinSwitch(id);
	}
	const onMax = function() {
		if (data.maximized && data.oldPosition) {
			data.animating = true;
			data.resizable = true;
			clearTimeout(data.timer);
			data.timer = setTimeout(() => {
				data.maximized = false;
				data.position.y = data.oldPosition.y;
				data.position.x = data.oldPosition.x;
				data.height = data.oldPosition.height;
				data.width = data.oldPosition.width;
				data.oldPosition = null;
				clearTimeout(data.timer);
				data.timer = setTimeout(() => {
					data.animating = false;
				}, 500);
			});
		} else {
			data.animating = true;
			data.resizable = false;
			clearTimeout(data.timer);
			data.timer = setTimeout(() => {
				data.maximized = true;
				data.oldPosition = {
					y: data.position.y,
					x: data.position.x,
					height: data.height,
					width: data.width
				};
				data.position.y = 0;
				data.position.x = 0;
				data.height = document.body.clientHeight * 0.95;
				data.width = document.body.clientWidth;
				clearTimeout(data.timer);
				data.timer = setTimeout(() => {
					data.animating = false;
				}, 500);
			});
		}
	}

	const onResize = function(direction) {
		data.resize = true;
		data.overlayShow = true;
		document.onmousemove = event => {
			if (data.resize) {
				let x = event.clientX;
				let y = event.clientY;
				let mx = document.body.clientWidth;
				let my = document.body.clientHeight * 0.95;
				x = x >= 0 ? (x >= mx ? mx : x) : 0;
				y = y >= 0 ? (y >= my ? my : y) : 0;
				if (direction.indexOf('top') >= 0) {
					data.height = data.height + (data.position.y - y);
					data.position.y = y;
				}
				if (direction.indexOf('left') >= 0) {
					data.width = data.width + (data.position.x - x);
					data.position.x = x;
				}
				if (direction.indexOf('bottom') >= 0) {
					data.height = data.height + (y - (data.position.y + data.height));
				}
				if (direction.indexOf('right') >= 0) {
					data.width = data.width + (x - (data.position.x + data.width));
				}
			}
		};
		document.onmouseup = () => {
			data.resize = false;
			data.overlayShow = false;
		};
	}

	const onMousedown = function(e) {
		let w = e.clientX - data.position.x;
		let h = e.clientY - data.position.y;
		if (!data.maximized) {
			data.drag = true;
			document.onmousemove = e => {
				if (data.drag) {
					data.position.x = e.clientX - w;
					data.position.y = e.clientY - h;
				}
			};
			document.onmouseup = () => {
				data.drag = false;
			};
		}
	}
</script>

<style lang="less" scoped>
	@import '../global';

	.window {
		position: absolute;
		border-radius: 5px;
		overflow: hidden;
		box-shadow: 0 10px 25px rgba(0, 0, 0, 0.4);

		&.animating {
			transition: all ease 0.5s;
		}

		.window-body {
			background: #f9f9f9;
			right: 0;
			bottom: 0;
			left: 0;
			position: absolute;
			top: var(--window-title-height); //@windowTitleHeight;
			width: 100%;
		}

		.window-title {
			width: 100%;
			background: var(--window-title-color);
			text-align: center;
			line-height: var(--window-title-height); //@windowTitleHeight;
			height: var(--window-title-height); //@windowTitleHeight;
			font-size: 1.0rem;
			cursor: default;
			color: rgba(160, 160, 160, 1);
			
			.icon {
				position: absolute;
				top: 4px;
				left: 5px;
				height: 18px;
				width: 18px;
				background-size: cover;
			}
		}

		&.focus {
			box-shadow: 0 10px 35px rgba(0, 0, 0, 0.6);

			.window-title {
				font-size: 1.0rem;
				background: var(--window-title-color-focus);
				color: #FFFFFF;
				text-shadow: 2px 2px 2px #000000;
			}

			z-index: 200;
		}

		&.maximized {
			.window-control .button.max {
				@margin: 5px;
				@diff: 2px;
				@w: 8px;
				@b: 1px;
				@top: 0px;
				@left: 0px;

				&:before {
					box-sizing: border-box;
					content: '';
					display: block;
					position: absolute;
					height: @w;
					width: @w;
					//left: ((@windowTitleHeight - 2 * @margin - @w) ./ 2)- @diff + @left;
					//top: ((@windowTitleHeight - 2 * @margin - @w) ./ 2) + @diff + @top;
					left: calc(((var(--window-title-height) - 2 * @margin - @w) / 2) - @diff + @left);
					top: calc(((var(--window-title-height) - 2 * @margin - @w) / 2) + @diff + @top);
					border: @b solid #fff;
					border-top-width: 2 * @b;
				}

				&:after {
					box-sizing: border-box;
					content: '';
					display: block;
					position: absolute;
					height: @w;
					width: @w;
					//left: ((@windowTitleHeight - 2 * @margin - @w) ./ 2) + @diff + @left;
					//top: ((@windowTitleHeight - 2 * @margin - @w) ./ 2) - @diff + @top;
					left: calc(((var(--window-title-height) - 2 * @margin - @w) / 2) + @diff + @left);
					top: calc(((var(--window-title-height) - 2 * @margin - @w) / 2) - @diff + @top);
					border: @b solid #fff;
					border-top-width: 2 * @b;
				}
			}
		}

		.window-control {
			@margin: 5px;
			position: absolute;
			right: 0;
			top: 0;
			height: calc(var(--window-title-height));

			.button {
				display: block;
				position: relative;
				width: calc(var(--window-title-height) - 2 * @margin);
				height: calc(var(--window-title-height) - 2 * @margin);
				margin: @margin @margin 0 0;
				float: left;
				border-radius: 3px;
			}

			.min {
				background: #81c2d0;

				&:before {
					box-sizing: border-box;
					@w: 12px;
					@h: 2px;
					content: '';
					display: block;
					position: absolute;
					height: @h;
					width: @w;
					//left: (@windowTitleHeight - 2 * @margin - @w) ./ 2;
					//bottom: ((@windowTitleHeight - 2 * @margin - @h) ./ 2) - 4px;
					left: calc((var(--window-title-height) - 2 * @margin - @w) / 2);
					bottom: calc(((var(--window-title-height) - 2 * @margin - @h) / 2) - 4px);
					background: #fff;
				}
			}

			.max {
				background: #659a65;

				&:before {
					box-sizing: border-box;
					@w: 12px;
					@b: 1px;
					content: '';
					display: block;
					position: absolute;
					height: @w;
					width: @w;
					// left: ((@windowTitleHeight - 2 * @margin - @w) / 2);
					// top: ((@windowTitleHeight - 2 * @margin - @w) / 2);
					left: calc(((var(--window-title-height) - 2 * @margin - @w) / 2));
					top: calc(((var(--window-title-height) - 2 * @margin - @w) / 2));
					border: @b solid #fff;
					border-top-width: 2 * @b;
				}
			}

			.Rotate(@deg) {
				transform: rotate(@deg);
				-webkit-transform: rotate(@deg);
				-moz-transform: rotate(@deg);
			}

			.close {

				&:before,
				&:after {
					@w: 14px;
					@h: 2px;
					content: '';
					display: block;
					position: absolute;
					height: @h;
					width: @w;
					// left: ((@windowTitleHeight - 2 * @margin - @w) / 2);
					// top: ((@windowTitleHeight - 2 * @margin - @h) / 2);
					left: calc(((var(--window-title-height) - 2 * @margin - @w) / 2));
					top: calc(((var(--window-title-height) - 2 * @margin - @h) / 2));
					background: #fff;
					.Rotate(45deg);
				}

				&:after {
					.Rotate(-45deg);
				}

				background: #d26262;
			}
		}

		@reactionWidth: 4px;

		.resize-side {
			position: absolute;
		}

		.resize-overlay {
			position: absolute;
			top: 0;
			left: 0;
			height: 100%;
			width: 100%;
		}

		.side-right {
			right: 0;
			bottom: 0;
			height: 100%;
			width: @reactionWidth;
			cursor: e-resize;
		}

		.side-bottom {
			right: 0;
			bottom: 0;
			width: 100%;
			height: @reactionWidth;
			cursor: s-resize;
		}

		.side-left {
			left: 0;
			top: 0;
			height: 100%;
			width: @reactionWidth;
			cursor: w-resize;
		}

		.side-top {
			left: 0;
			top: 0;
			width: 100%;
			height: @reactionWidth;
			cursor: n-resize;
		}

		.angle-bottom-right {
			right: 0;
			bottom: 0;
			width: @reactionWidth*2;
			height: @reactionWidth*2;
			cursor: se-resize;
		}

		.angle-bottom-left {
			left: 0;
			bottom: 0;
			width: @reactionWidth*2;
			height: @reactionWidth*2;
			cursor: sw-resize;
		}

		.angle-top-right {
			top: 0;
			right: 0;
			width: @reactionWidth*2;
			height: @reactionWidth*2;
			cursor: ne-resize;
		}

		.angle-top-left {
			top: 0;
			left: 0;
			width: @reactionWidth*2;
			height: @reactionWidth*2;
			cursor: nw-resize;
		}
	}

	.bounceIn {
		animation: bounceIn 0.5s;
	}

	.zoomOut {
		animation: zoomOut 0.6s;
	}
</style>